#ifndef CPUID_H
#define CPUID_H

#include "stdint.h"

/* all of the CPUID feature flags (EDX:ECX) */
struct cpuid_features_s
{
			/* EDX */
	bool	FPU, VME, DE, PSE,
			TSC, MSR, PAE, MCE,
			CX8, APIC, SEP, MTRR,
			PGE, MCA, CMOV, PAT,
			PSE_36, PSN, CLFSH, DS,
			ACPI, MMX, FXSR, SSE, 
			SSE2, SS, HTT, TM, PBE,
			/* ECX */
			SSE3, MONITOR, DS_CPL, VMX,
			SMX, EST, TM2, SSSE3,
			CNXT_ID, CMPXCHG16B,
			xTPR_Update_Control,
			PDCM, DCA, SSE4_1, SSE4_2, POPCNT;
};

struct cpuid_cache_s
{
    uint8_t  level;
    uint8_t  type;
    
    uint8_t  ways;
    uint8_t  partitions;
    uint16_t line_size;
    uint32_t sets;
    
    uint32_t cache_size;
};

struct perfmon_s
{
	uint8_t  version;
	uint8_t  ncounters;
	uint8_t  counter_width;
	uint8_t  ebx_width;
	uint32_t available_events;
	uint8_t  nC0, nC1, nC2, nC3, nC4;
};

struct cpuid_s
{
    struct perfmon_s perfmon;

    uint32_t max_basic_input,
             max_ext_input;
    uint8_t  cpu_signature[13];
    
    uint8_t  stepping, 
             model,
             family,
             type,
             ext_model,
             ext_family;
    uint16_t cache_line_size;
    
    uint32_t features_ecx, features_edx;
    struct cpuid_features_s features;
    uint8_t  sse_max_major, sse_max_minor;
    
    uint8_t  cpu_brand[49];

    struct   cpuid_cache_s cache_info[32];
    uint8_t  cache_count;
    
    uint8_t  l2_assoc;
    uint16_t l2_cache_size;
    uint8_t  l2_cache_line_size; 
} cpuid;

void parse_cpuid(void);

#endif
